#include <libnetwork/share.h>
#include <libnetwork/client.h>

// Initialize internal functions
// End internal functions

SOCK *client_setup(conn_host, conn_port, is_ssl, certificate, key)
char *conn_host;
int conn_port;
bool is_ssl;
char *certificate, *key;
{
 struct hostent *he;
 SOCK *_new_socket = malloc(sizeof(SOCK) * 1);

 _init_socket_variable(_new_socket);

 _new_socket->_status += STATUS_CLI;

 if ((he=gethostbyname(conn_host)) == NULL) {
  err("Error: libcnet.so->client.c->client_setup(): failed to gethostbyname()", _new_socket);
  _new_socket->_status += STATUS_INIT_ERROR;
  return _new_socket;
 }

 if ((_new_socket->_sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
  err("Error: libcnet.so->client.c->client_setup(): failed to socket()", _new_socket);
  _new_socket->_status += STATUS_INIT_ERROR;
  return _new_socket;
 }

 _new_socket->_their_addr.sin_family = AF_INET;
 _new_socket->_their_addr.sin_port = htons(conn_port);
 memcpy(&_new_socket->_their_addr.sin_addr.s_addr, he->h_addr, he->h_length);
 memset(_new_socket->_their_addr.sin_zero, '\0', sizeof(_new_socket->_their_addr.sin_zero));

 _new_socket->_status += STATUS_INIT;

 if (connect(_new_socket->_sockfd, (struct sockaddr *)&_new_socket->_their_addr,sizeof(_new_socket->_their_addr)) == -1) {
  err("Error: libcnet.so->client.c->client_setup(): failed to connect()", _new_socket);
  _new_socket->_status += STATUS_INIT_ERROR;
  return _new_socket;
 }

 if( is_ssl ) {
  int _x;
  _new_socket->_status += STATUS_ENC;

  if( certificate == NULL || key == NULL ) {
   err("Error: libcnet.a->client.c->client_setup(): need PEM cert and key for SSL", _new_socket);
   _new_socket->_status += STATUS_INIT_ERROR;
   return _new_socket;
  }

  SSL_library_init();
  _new_socket->_ssl_ctx = SSL_CTX_new(SSLv2_method());

  for( _x = 0; certificate[_x] != '\0'; _x ++ ) {
   _new_socket->cert[_x] = certificate[_x];
  }
  _new_socket->cert[_x] = '\0';

  for( _x = 0; key[_x] != '\0'; _x ++ ) {
   _new_socket->key[_x] = key[_x];
  }
  _new_socket->key[_x] = '\0';

  if( SSL_CTX_use_certificate_file(_new_socket->_ssl_ctx, _new_socket->cert, SSL_FILETYPE_PEM) != 1) {
   err("Error: libcnet.a->client.c->client_setup(): failed to SSL_CTX_use_certificate_file()", _new_socket);
   _new_socket->_status += STATUS_INIT_ERROR;
   return _new_socket;
  }

  if( SSL_CTX_use_PrivateKey_file(_new_socket->_ssl_ctx, _new_socket->key, SSL_FILETYPE_PEM) != 1) {
   err("Error: libcnet.a->client.c->client_setup(): failed to SSL_CTX_use_PrivateKey_file()", _new_socket);
   _new_socket->_status += STATUS_INIT_ERROR;
   return _new_socket;
  }

  _new_socket->_ssl = SSL_new(_new_socket->_ssl_ctx);

  if( SSL_set_fd(_new_socket->_ssl, _new_socket->_sockfd) == 0 ) {
   err("Error: libcnet.so->client.c->client_setup(): failed to SSL_set_fd()", _new_socket);
   _new_socket->_status += STATUS_INIT_ERROR;
   return _new_socket;
  }

  if( SSL_connect(_new_socket->_ssl) != 1 ) {
    ERR_print_errors_fp(stdout);
  }
 }

 _new_socket->_status += STATUS_CONN;

 return _new_socket;
}

